package cn.admin.remoting.impl;

import cn.admin.remoting.Client;
import cn.admin.remoting.ResponseFuture;

import java.io.Serializable;
import java.util.concurrent.atomic.AtomicLong;

public class ConnectionRequest implements RemotingMessage {

    private RequestContext ctx;
    private transient Object appRequest;
    private transient Client client;
    private transient long respTimeout;
    private transient ResponseFuture respFuture;
    private final transient ClassLoader loader;

    private ConnectionRequest() {
        this.ctx = new RequestContext();
        this.loader = null;
    }

    public ConnectionRequest(Object appRequest) {
        this(appRequest,null);
    }

    public ConnectionRequest(Object appRequest,ClassLoader responseLoader) {
        this.ctx = new RequestContext();
        this.appRequest = appRequest;
        this.ctx.id = IDGenerator.getNextId();
        this.loader = responseLoader;
    }

    public RequestContext getCtx() {
        return ctx;
    }

    public void setCtx(RequestContext ctx) {
        this.ctx = ctx;
    }

    public Object getAppRequest() {
        return appRequest;
    }

    public void setAppRequest(Object appRequest) {
        this.appRequest = appRequest;
    }

    public Client getClient() {
        return client;
    }

    public void setClient(Client client) {
        this.client = client;
    }

    public long getRespTimeout() {
        return respTimeout;
    }

    public void setRespTimeout(long respTimeout) {
        this.respTimeout = respTimeout;
    }

    public ResponseFuture getRespFuture() {
        return respFuture;
    }

    public void setRespFuture(ResponseFuture respFuture) {
        this.respFuture = respFuture;
    }

    public ClassLoader getClassLoader() {
        return loader;
    }

    public long getId() {
        return this.ctx.id;
    }

    public byte getDirection() {
        return this.ctx.direction;
    }

    public void setDirection(byte direction) {
        this.ctx.direction = direction;
    }

    @Override
    public String toString() {
        return "ConnectionRequest[" +
                "requestId=" + this.ctx.id +
                ", protocol=" + this.ctx.serializeProtocol +
                ", direction=" + this.ctx.direction +
                ", appRequest=" + this.appRequest +
                "]";
    }

    @Override
    public long getMessageId() {
        return this.ctx.id;
    }

    public void setSerializeProtocol(byte serializeProtocol) {
        this.ctx.serializeProtocol = serializeProtocol;
    }

    @Override
    public byte getSerializeProtocol() {
        return this.ctx.serializeProtocol;
    }

    public static class IDGenerator {

        private static AtomicLong id = new AtomicLong(0L);

        public static long getNextId() {
            if (id.longValue() > 9223372036854774807L) {
                id.getAndSet(0L);
            }

            return id.incrementAndGet();
        }

    }

    private class RequestContext implements Serializable {

        private long id;
        private transient byte serializeProtocol;
        private transient byte direction;

        private RequestContext() {
            this.serializeProtocol = 1;
            this.direction = 2;
        }

    }

}
